﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using Viettel.VOFFICE.DAO.DAL.Paging;
using Viettel.VOFFICE.DAO.Models;

namespace Viettel.VOFFICE.DAO.DAL.Repository
{
    /// <summary>
    /// xử lý phòng ban trong hệ thống
    /// </summary>
    public class DepartmentRepository : IRepository<v_Department>
    {
        private VOFFICEContext context;

        public DepartmentRepository(VOFFICEContext context)
        {
            if (context == null)
            {
                throw new Exception("Context must be init");
            }
            this.context = context;
        }

        #region Đệ quy để dựng cây phòng ban
        //chứa cây
        private List<v_Department> _tree;

        /// <summary>
        /// Tạo cây phòng ban, bằng cách đệ quy
        /// </summary>
        /// <returns></returns>
        public List<v_Department> DeptTree()
        {
            _tree = new List<v_Department>();
            var grand = context.v_Department.Where(o => (o.ParentId == null || o.ParentId == 0) && o.IsActive == true).Select(o => o).ToList();
            if (grand.Any())
            {
                foreach (var d in grand)
                {
                    d.Node = 0;
                    _tree.Add(d);
                    DQ(d, d.Node);
                }
            }
            return _tree;
        }

        /// <summary>
        /// hàm đệ quy lấy ra các phòng ban con của nhánh
        /// </summary>
        /// <param name="d"></param>
        protected void DQ(v_Department d, int node)
        {
            var grand = context.v_Department.Where(o => o.ParentId == d.Id && o.IsActive == true).Select(o => o).ToList();
            if (grand.Any())
            {
                foreach (var dept in grand)
                {
                    dept.Node = node + 1;
                    _tree.Add(dept);
                    DQ(dept,dept.Node);
                }
            }
            return;
        }
        #endregion
        /// <summary>
        /// lấy toàn bô danh sách phòng ban
        /// </summary>
        /// <returns></returns>
        public IEnumerable<v_Department> Get()
        {
            return context.v_Department.Where(o => o.IsActive == true);
        }
        /// <summary>
        /// lấy phòng ban bởi id
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public v_Department GetById(object id)
        {
            return context.v_Department.Find(int.Parse(id.ToString()));
        }

        /// <summary>
        /// lấy phòng ban bởi tên phòng ban
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public IEnumerable<v_Department> FindByName(object s)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// thêm phòng ban mới
        /// </summary>
        /// <param name="T"></param>
        public void Insert(v_Department T)
        {
            context.v_Department.Add(T);
            Save();
        }

        /// <summary>
        /// xóa phòng ban bởi id của phòng ban
        /// </summary>
        /// <param name="id"></param>
        public void Delete(object id)
        {
            var item = GetById(id);
            if (null != item)
            {
                context.v_Department.Attach(item);
                context.v_Department.Remove(item);
                Save();
            }
        }

        /// <summary>
        /// xóa một phòng ban
        /// </summary>
        /// <param name="T"></param>
        public void Delete(v_Department T)
        {
            if (null != T)
            {
                context.v_Department.Attach(T);
                context.v_Department.Remove(T);
                Save();
            }
        }

        /// <summary>
        /// Cập nhập phòng ban
        /// </summary>
        /// <param name="T"></param>
        public void Update(v_Department T)
        {
            context.Entry(T).State = EntityState.Modified;
            Save();
        }

        public void Save()
        {
            context.SaveChanges();
        }

        #region Extend Repository

        public IEnumerable<v_UsersInDepartment> GetUserInDepartmentById(int id)
        {
            return context.v_UsersInDepartment.Where(o => o.DeparmentId == id);
        }
        public bool CheckExistsUid(string userName, int deptId)
        {
            return context.v_UsersInDepartment.Any(o => o.aspnet_Users.UserName == userName && o.DeparmentId == deptId);
        }
        public bool RemoveUserInDepts(System.Guid userId, int deptId)
        {
            var uid = context.v_UsersInDepartment.Find(userId, deptId);
            if(uid!=null)
            {
                context.v_UsersInDepartment.Remove(uid);
                Save();
                return true;
            }
            return false;
        }
        public void AddUserToDepartment(v_UsersInDepartment model)
        {
            context.v_UsersInDepartment.Add(model);
            Save();
        }
        public IEnumerable<v_Department> GetDeptByParentId(int? parentId)
        {
            return context.v_Department.Where(o => o.ParentId == parentId);
        }
        public v_Department GetRootDepartment()
        {
            return context.v_Department.FirstOrDefault(o => o.ParentId.Equals(null));
        }
        public PagedList<v_Department> GetWithPaging(int? parentId, int pageIndex, int pageSize)
        {
            return context.v_Department.Where(o => o.ParentId == parentId).OrderByDescending(o => o.UpdatedAt).Paginate(pageIndex, pageSize);
        }
        #endregion

    }
}
